// -----------------------------------------------------------------------
//  <copyright file="TextJsonExtensions.cs" company="LiuliuSoft">
//      Copyright (c) 2022-2025 DaprPlus. All rights reserved.
//  </copyright>
//  <site>https://dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2025-03-04 18:03</last-date>
// -----------------------------------------------------------------------

using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Components;

namespace DaprPlus.Json;

public static class TextJsonExtensions
{
    /// <summary>
    /// 默认的JSON序列化选项
    /// </summary>
    private static readonly JsonSerializerOptions _defaultOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        PropertyNameCaseInsensitive = true,
        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
        WriteIndented = false,
        Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
        ReferenceHandler = ReferenceHandler.IgnoreCycles
    };

    /// <summary>
    /// 将对象转换为JSON字符串
    /// </summary>
    /// <param name="obj">要转换的对象</param>
    /// <param name="options">JSON序列化选项，默认为null</param>
    /// <returns>JSON字符串</returns>
    public static string? ToTextJson(this object? obj, JsonSerializerOptions? options = null)
    {
        if (obj == null)
        {
            return null;
        }

        return JsonSerializer.Serialize(obj, options ?? _defaultOptions);
    }

    /// <summary>
    /// 将JSON字符串反序列化为指定类型的对象
    /// </summary>
    /// <typeparam name="T">目标类型</typeparam>
    /// <param name="json">JSON字符串</param>
    /// <param name="options">JSON反序列化选项，默认为null</param>
    /// <returns>反序列化后的对象</returns>
    public static T? FromTextJson<T>(this string json, JsonSerializerOptions? options = null)
    {
        if (string.IsNullOrEmpty(json))
        {
            return default;
        }

        return JsonSerializer.Deserialize<T>(json, options ?? _defaultOptions);
    }

    /// <summary>
    /// 将JSON字符串反序列化为指定类型的对象
    /// </summary>
    /// <param name="json">JSON字符串</param>
    /// <param name="type">目标类型</param>
    /// <param name="options">JSON反序列化选项，默认为null</param>
    /// <returns>反序列化后的对象</returns>
    public static object? FromTextJson(this string json, Type type, JsonSerializerOptions? options = null)
    {
        if (string.IsNullOrEmpty(json))
        {
            return null;
        }

        return JsonSerializer.Deserialize(json, type, options ?? _defaultOptions);
    }

    public static object? ConvertToObject(this JsonElement element)
    {
        return element.ValueKind switch
        {
            JsonValueKind.String => element.GetString(),
            JsonValueKind.Number => HandleNumber(element),
            JsonValueKind.True => true,
            JsonValueKind.False => false,
            JsonValueKind.Null => null,
            JsonValueKind.Array => HandleArray(element),
            JsonValueKind.Object => HandleObject(element),
            _ => throw new NotSupportedException($"Unsupported ValueKind: {element.ValueKind}")
        };
    }

    // 处理数字类型（自动识别为 int/long/double/decimal）
    private static object HandleNumber(JsonElement element)
    {
        if (element.TryGetInt32(out int intValue)) return intValue;
        if (element.TryGetInt64(out long longValue)) return longValue;
        if (element.TryGetDouble(out double doubleValue)) return doubleValue;
        return element.GetDecimal(); // 高精度小数
    }

    // 处理数组
    private static List<object> HandleArray(JsonElement element)
    {
        var list = new List<object>();
        foreach (var item in element.EnumerateArray())
        {
            list.Add(item.ConvertToObject());
        }
        return list;
    }

    // 处理对象
    private static Dictionary<string, object> HandleObject(JsonElement element)
    {
        var dict = new Dictionary<string, object>();
        foreach (var prop in element.EnumerateObject())
        {
            dict[prop.Name] = prop.Value.ConvertToObject();
        }
        return dict;
    }
}
